package top.choviwu.garbage.sort.util;

import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.jsoup.select.Evaluator;
import org.springframework.util.CollectionUtils;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class SpiderUtils {

    private static final ExecutorService pool = Executors.newFixedThreadPool(10);
    static String host;

    public static void downLoad(String url, String path) {
        try {
            Document parse = Jsoup.parse(new URL(host + url).openStream(), "utf8", host + url);
            findStatic(parse, path);
            String s = replaceDocRoot(parse, path);
            write(s, path + "index.html");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void findStatic(Document document, String path) {
        Elements script = document.getElementsByTag("script");
        script.forEach(element -> {
            String src = element.attr("src");
            if (StringUtils.isBlank(src)) {
                return;
            }
            String[] split = src.split("/");
            StringBuilder builder = new StringBuilder(path);
            for (int i = 0; i < split.length; i++) {
                if (StringUtils.isBlank(split[i])) {
                    continue;
                }
                try {
                    boolean exists = Files.exists(Paths.get(builder.append("/").append(split[i]).toString()));
                    if (!exists) {
                        try {
                            if (builder.toString().lastIndexOf(".js") > -1) {
                                Files.createFile(Paths.get(builder.toString()));
                                //创建对象
                                downLoadStatic(host + src,builder.toString());
                            } else {
                                Files.createDirectories(Paths.get(builder.toString()));
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }catch (Exception e) {
                    continue;
                }

            }
        });

        Elements css = document.getElementsByTag("link");
        css.forEach(element -> {
            String src = element.attr("href");
            if (!"stylesheet".equals(element.attr("rel"))) {
                return;
            }
            String[] split = src.split("/");
            StringBuilder builder = new StringBuilder(path);
            for (int i = 0; i < split.length; i++) {

                boolean exists = Files.exists(Paths.get(builder.append("/").append(split[i]).toString()));
                if (!exists) {
                    try {
                        if (builder.toString().lastIndexOf(".css") > -1) {
                            Files.createFile(Paths.get(builder.toString()));
                            //创建对象
                            downLoadStatic(host + src,builder.toString());
                        } else {
                            Files.createDirectories(Paths.get(builder.toString()));
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }

            }
        });

        Elements img = document.getElementsByTag("img");
        img.forEach(element -> {
            String src = element.attr("src");
            if (StringUtils.isBlank(element.attr("src"))) {
                return;
            }
            String[] split = src.split("/");
            StringBuilder builder = new StringBuilder(path);
            for (int i = 0; i < split.length; i++) {

                boolean exists = Files.exists(Paths.get(builder.append("/").append(split[i]).toString()));
                if (!exists) {
                    try {
                        if (builder.toString().lastIndexOf(".jpg") > -1) {
                            Files.createFile(Paths.get(builder.toString()));
                            downLoadStatic(host + src,builder.toString());
                        } else {
                            Files.createDirectories(Paths.get(builder.toString()));
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }

            }
        });

    }

    private static void downLoadStatic(String ttt, String path) {
        try {
            URL url = new URL(ttt);
            URLConnection connection = url.openConnection();
            //打开链接
            HttpURLConnection conn = (HttpURLConnection)url.openConnection();
            //设置请求方式为"GET"
            conn.setRequestMethod("GET");
            //超时响应时间为5秒
            conn.setConnectTimeout(5 * 1000);
            //通过输入流获取图片数据
            InputStream inStream = conn.getInputStream();
            //得到图片的二进制数据，以二进制封装得到数据，具有通用性
            byte[] data = readInputStream(inStream);
            //new一个文件对象用来保存图片，默认保存当前工程根目录
            File imageFile = new File(path.toString());
            //创建输出流
            FileOutputStream outStream = new FileOutputStream(imageFile);
            //写入数据
            outStream.write(data);
            //关闭输出流
            outStream.close();
        }catch (Exception e) {

        }
    }


    private static class Matcher extends Evaluator {

        private Pattern pattern;

        public Matcher(Pattern pattern) {
            this.pattern = pattern;
        }

        @Override
        public boolean matches(Element element, Element element1) {
            java.util.regex.Matcher m = this.pattern.matcher(element.html());
            return m.find();
        }
    }

    private static void write(String html, String path) {
        try(BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(path))) {
            bufferedWriter.write(html);
            bufferedWriter.newLine();
            bufferedWriter.flush();
            System.out.println(path + "========================写入成功===============" );
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static String replaceDocRoot(Document document, String rootPath) {
        Elements script = document.getElementsByTag("script");
        script.forEach(c->{
            String src = c.attr("src");
            if (StringUtils.isBlank(src)) {
                return;
            }
           c.attr("src", rootPath + c.attr("src"));
        });

        Elements link = document.getElementsByTag("link");
        link.forEach(c->{
            if (!"stylesheet".equals(c.attr("rel"))) {
                return;
            }
            c.attr("href", rootPath + c.attr("href"));
        });

        Elements img = document.getElementsByTag("img");
        img.forEach(c->{
            String src = c.attr("src");
            if (StringUtils.isBlank(src)) {
                return;
            }
            c.attr("src", rootPath + c.attr("src"));
        });
        return document.html();
    }

    public static byte[] readInputStream(InputStream inStream) throws Exception{
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        //创建一个Buffer字符串
        byte[] buffer = new byte[1024];
        //每次读取的字符串长度，如果为-1，代表全部读取完毕
        int len = 0;
        //使用一个输入流从buffer里把数据读取出来
        while( (len=inStream.read(buffer)) != -1 ){
            //用输出流往buffer里写入数据，中间参数代表从哪个位置开始读，len代表读取的长度
            outStream.write(buffer, 0, len);
        }
        //关闭输入流
        inStream.close();
        //把outStream里的数据写入内存
        return outStream.toByteArray();
    }

    public static void main(String[] args) {
        SpiderUtils.host = "https://www.genban.org/";
        downLoad("", SpiderUtils.class.getResource("/").getPath().substring(1));
    }
}
